#include "tw80st.h"
#include "./stream.h"
#include "sys_timer.h"

static uint8_t sensor_buf[17];
static uint8_t sensor_buf_index = 0;

static uint8_t ChenkSensor() {
  uint8_t check = 0;
  uint8_t i = 2;
  for ( ; i < 16; i++) {
    check += sensor_buf[i];
  }

  // if ((check & 0xFF) != sensor_buf[16])
  //   return 0;
  return 1;
}

// byte[0-6]: Start(0xaa):VoutH:VoutL:VrefH:VrefL:Check:End(0xff) 
bool TW80ST::Pm25Parse(uint8_t ch) {
  static uint8_t start_flag = 0;
  if (start_flag == 0 && ch == 0x3C) {
    start_flag = 1;
  }
  if (start_flag) {
    sensor_buf[sensor_buf_index++] = ch;
    if (sensor_buf_index == 2 && ch != 0x02) {
      sensor_buf_index = start_flag = 0;
    }
    if (sensor_buf_index >= 17) {
      sensor_buf_index = start_flag = 0;
      if (ChenkSensor()) {
        pm25_val_ = sensor_buf[1] << 8 | sensor_buf[2];
        recv_time_ = CurMillis();
        return true;
      }
    }
  }
  return false;
}

void TW80ST::Init() {
}

int32_t TW80ST::GetValue() {
  if ((recv_time_ + 5000) < CurMillis()) {
    return -1;  // sensor fail
  }
  return pm25_val_;
}

bool TW80ST::Loop() {
  uint8_t ch;
  while (StreamReadC(SOURCE_USART2, &ch) == STREAM_SUCCESS) {
    if (Pm25Parse(ch)) {
      TW80ST_t * tw = (TW80ST_t *)sensor_buf;
      pm25_val_ = (tw->PM25_H >> 8) | tw->PM25_L;
      if (tw->temperature & 0x80) {
        temperature_ = - ((tw->temperature & 0x7f) * 10 + tw->temp_decimals / 10);
      } else {
        temperature_ = tw->temperature * 10 + tw->temp_decimals / 10;
      }
      humdity_ = tw->humidity * 10 + tw->humdity_decimals;
      co2_ = tw->CO2_H << 8 | tw->CO2_L;
      ch2o_ = tw->CH2O_H << 8 | tw->CH2O_L;
      tvoc_ = tw->TVOC_H << 8 | tw->TVOC_L;
      pm10_ = tw->PM10_H << 8 | tw->PM10_L;
      return true;
    }
  }
  return false;
}